package it.uniroma2.art.coda.core;

import it.uniroma2.art.coda.exception.CODAComponentNotSetException;
import it.uniroma2.art.coda.exception.FelixInitializationException;
import it.uniroma2.art.coda.exception.PRParserException;
import it.uniroma2.art.coda.extension.CODAOSGiManger;
import it.uniroma2.art.coda.interfaces.IdentityResolverInterface;
import it.uniroma2.art.coda.interfaces.ProjectionRulesDeciderInterface;
import it.uniroma2.art.coda.interfaces.ResourcesSmartSuggesterInterface;
import it.uniroma2.art.coda.interfaces.TriplesSmartSuggesterInterface;
import it.uniroma2.art.coda.projectionrule.GraphStruct;
import it.uniroma2.art.coda.projectionrule.IfElseStruct;
import it.uniroma2.art.coda.projectionrule.ParserPR;
import it.uniroma2.art.coda.projectionrule.PlaceholderStruct;
import it.uniroma2.art.coda.projectionrule.ProjectionRule;
import it.uniroma2.art.coda.projectionrule.ProjectionRulesModel;
import it.uniroma2.art.coda.projectionrule.graph.GraphSingleElemPlaceholder;
import it.uniroma2.art.coda.projectionrule.graph.GraphSingleElemUri;
import it.uniroma2.art.coda.projectionrule.graph.GraphSingleElemVar;
import it.uniroma2.art.coda.projectionrule.graph.GraphSingleElement;
import it.uniroma2.art.coda.structures.ARTNodeAndString;
import it.uniroma2.art.coda.structures.ARTTriple;
import it.uniroma2.art.coda.structures.BindLabelToExistingARTURIResource;
import it.uniroma2.art.coda.structures.CasAnnotationStructure;
import it.uniroma2.art.coda.structures.CodaFinalSuggestions;
import it.uniroma2.art.coda.structures.PreviousDecisionSingleElement;
import it.uniroma2.art.coda.structures.PreviousDecisions;
import it.uniroma2.art.coda.structures.SelectedProjectionRules;
import it.uniroma2.art.coda.structures.ResourcesSmartSuggesterStruct;
import it.uniroma2.art.coda.structures.SuggOntologyCoda;
import it.uniroma2.art.coda.structures.TriplesSmartSuggestionStruct;
import it.uniroma2.art.coda.structures.Tuple;
import it.uniroma2.art.coda.structures.WhereResult;
import it.uniroma2.art.coda.structures.depends.DependencyObjOneParam;
import it.uniroma2.art.coda.structures.depends.DependencyObjThreeParam;
import it.uniroma2.art.coda.structures.depends.DependencyObjTwoParam;
import it.uniroma2.art.coda.structures.depends.DependencyObjVarParam;
import it.uniroma2.art.coda.structures.depends.DependencyObject;
import it.uniroma2.art.owlart.exceptions.ModelAccessException;
import it.uniroma2.art.owlart.exceptions.ModelUpdateException;
import it.uniroma2.art.owlart.exceptions.QueryEvaluationException;
import it.uniroma2.art.owlart.exceptions.UnsupportedQueryLanguageException;
import it.uniroma2.art.owlart.model.ARTNode;
import it.uniroma2.art.owlart.model.ARTURIResource;
import it.uniroma2.art.owlart.models.RDFModel;
import it.uniroma2.art.owlart.query.Binding;
import it.uniroma2.art.owlart.query.MalformedQueryException;
import it.uniroma2.art.owlart.query.Query;
import it.uniroma2.art.owlart.query.QueryLanguage;
import it.uniroma2.art.owlart.query.TupleBindings;
import it.uniroma2.art.owlart.query.TupleBindingsIterator;
import it.uniroma2.art.owlart.query.TupleQuery;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.uima.cas.FSIterator;
import org.apache.uima.jcas.JCas;
import org.apache.uima.jcas.tcas.Annotation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * This class represent the entry point to the CODA framework and the external tool should only use this
 * directly
 * 
 * @author Andrea Turbati
 */
/**
 * @author Andrea Turbati
 * 
 */
public class CODACore {
	private FSIterator iterAnnotation = null;
	private JCas jcas = null;

	private PreviousDecisions prevDecision;

	private RDFModel rdfModel;

	private HashMap<String, ParserPR> projectionRuleParserMap = null;
	// These maps contains all the possible implementation of the five modules with their ID
	private HashMap<String, ProjectionRulesDeciderInterface> projectionRulesDeciderMap = null;
	private HashMap<String, IdentityResolverInterface> identityResolverMap = null;
	private HashMap<String, ResourcesSmartSuggesterInterface> resourcesSmartSuggesterMap = null;
	private HashMap<String, TriplesSmartSuggesterInterface> triplesSmartSuggesterMap = null;

	private ParserPR projectionRuleParserSelected = null;
	// These are the selected implementations to be used (one for every module)
	private ProjectionRulesDeciderInterface projectionRuleDeciderSelected = null;
	private IdentityResolverInterface identityResolverSelected = null;
	private ResourcesSmartSuggesterInterface resourcesSmartSuggesterSelected = null;
	private TriplesSmartSuggesterInterface triplesSmartSuggesterSelected = null;


	// This manage all the extension points
	private CODAOSGiManger codaOSGiManger = null;

	// These int represent the maximum number of solution that each module should return, 0 means no limit
	private int maxNumAnswerPD = 0;
	private int maxNumAnswerIR = 0;
	private int maxNumAnswerRSS = 0;
	private int maxNumAnswerTSS = 0;

	// This is a model of the ProjectionRule
	ProjectionRulesModel prModel = null;

	// possible type of dependency

	// one parameters
	private String lastDep = "last";
	// private String nextDep = "next";
	// private String encloseDep = "enclose";

	// two parameters
	private String previousDep = "previous";
	// private String previousUpTo = "previousUpTo_";

	// three parameters

	// multiple parameters
	private String lastOneOfDep = "lastOneOf";

	@SuppressWarnings("unused")
	private static Logger logger = LoggerFactory.getLogger(CODACore.class);

	/**
	 * Constructor of this class
	 */
	public CODACore() {
	}

	/**
	 * Initialize the framework and should be called just after the constructor, before all other methods
	 * 
	 * @param jcas
	 *            the CAS received form the UIMA AE or AAE
	 * @param oSGiDir
	 *            the directory in which felix will store the cache for its bundles
	 * @param rootDir
	 *            the directory in which felix will search for the bundle using a particular search strategy
	 * @param subDirPresent
	 *            true if in the rootDir there are the subdirectories in which to look for directory
	 *            containing bundles, false otherwise
	 * @param projRulePath
	 *            the path of the Projection Rule file
	 * @param rdfModel
	 *            the ontology model created with a particular repository manager
	 * @param prevDecision
	 *            is the structure containing the previous decision taken by the tool using the suggestions
	 *            provided by CODA
	 * @throws FelixInitializationException
	 * @throws PRParserException
	 */
	public void initialize(JCas jcas, File oSGiDir, String rootDir, boolean subDirPresent,
			String projRulePath, RDFModel rdfModel, PreviousDecisions prevDecision)
			throws FelixInitializationException, PRParserException {
		setJCas(jcas);

		codaOSGiManger = CODAOSGiManger.initialize(oSGiDir);

		this.prevDecision = prevDecision;

		// search for the bundle
		codaOSGiManger.loadProjectionRulesParser(rootDir, subDirPresent);
		codaOSGiManger.loadProjectionRulesDecider(rootDir, subDirPresent);
		codaOSGiManger.loadIdentityResolver(rootDir, subDirPresent);
		codaOSGiManger.loadResourcesSmartSuggestion(rootDir, subDirPresent);
		codaOSGiManger.loadTriplesSmartSuggestion(rootDir, subDirPresent);
		// remove the bundle loaded in the previous execution of CODA, but not present in this one
		codaOSGiManger.removeOldBundle();

		projectionRuleParserMap = codaOSGiManger.getProjectionRuleParserMap();
		projectionRulesDeciderMap = codaOSGiManger.getProjectonRulesDeciderMap();
		identityResolverMap = codaOSGiManger.getIdentityResolutionMap();
		resourcesSmartSuggesterMap = codaOSGiManger.getResourcesSmartSuggestionMap();
		triplesSmartSuggesterMap = codaOSGiManger.getSmartSuggestionTripleMap();
		
		// Set the model for the projectionRule, this is the only place where the projection rule structure is
		// set at the moment the first prParser found in the map is used (the ANTLR one)
		prModel = new ProjectionRulesModel();
		// ParserPR xmlParserPR = new XMLParserPR(); // at the moment the PR File is only written in XML
		// xmlParserPR.initialize(prModel, projRulePath);
		// xmlParserPR.startParsingPR();
		String prpKey = projectionRuleParserMap.keySet().iterator().next();
		projectionRuleParserSelected = projectionRuleParserMap.get(prpKey);
		projectionRuleParserSelected.initialize(prModel, projRulePath, this);
		projectionRuleParserSelected.parsePR();
		// Set the rdfModel
		setRDFModel(rdfModel);

	}

	/**
	 * Close the rdfModel and stop Felix
	 * 
	 * @throws ModelUpdateException
	 */
	public void stopAndClose() throws ModelUpdateException {
		rdfModel.close();
		codaOSGiManger.stop();
	}

	/**
	 * Set the UIMA CAS containing all the UIMA annotation
	 * 
	 * @param jcas
	 *            the jcas that will be set
	 */
	public void setJCas(JCas jcas) {
		this.jcas = jcas;
		if (jcas != null) {
			iterAnnotation = this.jcas.getAnnotationIndex().iterator();
		}
	}

	/**
	 * Set the ontology model (RDFModel)
	 * 
	 * @param rdfModel
	 *            the ontology model
	 */
	public void setRDFModel(RDFModel rdfModel) {
		this.rdfModel = rdfModel;
		setProjectionRulesDecider(projectionRuleDeciderSelected);
		setIdentityResolver(identityResolverSelected);
		setResourcesSmartSuggester(resourcesSmartSuggesterSelected);
		setTriplesSmartSuggester(triplesSmartSuggesterSelected);
	}

	/**
	 * Close the RDFModel
	 * 
	 * @throws ModelUpdateException
	 */
	public void closeRDFModel() throws ModelUpdateException {
		rdfModel.close();
	}

	/**
	 * Get the Projection Rule Model
	 * 
	 * @return the projection rule model
	 */
	public ProjectionRulesModel getProjRuleModel() {
		return prModel;
	}

	/**
	 * This method get the Projection Rule Decider Annotation Map
	 * 
	 * @return the Projection Disambiguation Map
	 */
	public HashMap<String, ProjectionRulesDeciderInterface> getProjectionRulesDeciderMap() {
		return projectionRulesDeciderMap;
	}

	/**
	 * This method get the Identity Resolution Annotation Map
	 * 
	 * @return the Identity Resolution Annotation Map
	 */
	public HashMap<String, IdentityResolverInterface> getIdentityResolverMap() {
		return identityResolverMap;
	}

	/**
	 * This method get the Smart Suggestion Resources Map
	 * 
	 * @return the Smart Suggestion Map
	 */
	public HashMap<String, ResourcesSmartSuggesterInterface> getResourcesSmartSuggesterMap() {
		return resourcesSmartSuggesterMap;
	}
	
	/**
	 * This method get the Smart Suggestion Triple Map
	 * 
	 * @return the Smart Suggestion Triple Map
	 */
	public HashMap<String, TriplesSmartSuggesterInterface> getTriplesSmartSuggesterMap() {
		return triplesSmartSuggesterMap;
	}

	// These five following methods add the PRModel and OWLARTAPi, so the must be invoked after the method
	// initialize

	/**
	 * This method set the Projection Rules Decider
	 * 
	 * @param projectionDisambiguation
	 *            the Projection Disambiguation Annotation
	 */
	public void setProjectionRulesDecider(ProjectionRulesDeciderInterface projectionDisambiguation) {
		projectionRuleDeciderSelected = projectionDisambiguation;
		if (projectionRuleDeciderSelected != null) {
			projectionRuleDeciderSelected.setProjectionRuleModel(prModel);
			projectionRuleDeciderSelected.setRDFModel(rdfModel);
			projectionRuleDeciderSelected.setCODACore(this);
		}
	}

	/**
	 * This method set the Identity Resolution Annotation
	 * 
	 * @param identityResolution
	 *            the Identity Resolution Annotation
	 */
	public void setIdentityResolver(IdentityResolverInterface identityResolution) {
		identityResolverSelected = identityResolution;
		if (identityResolverSelected != null) {
			identityResolverSelected.setProjectionRuleModel(prModel);
			identityResolverSelected.setRDFModel(rdfModel);
			identityResolverSelected.setCODACore(this);
		}
	}

	/**
	 * This method set the Smart Suggestion Resources
	 * 
	 * @param resourcesSmartSuggester
	 *            the Smart Suggestion Resources
	 */
	public void setResourcesSmartSuggester(ResourcesSmartSuggesterInterface resourcesSmartSuggester) {
		resourcesSmartSuggesterSelected = resourcesSmartSuggester;
		if (resourcesSmartSuggesterSelected != null) {
			resourcesSmartSuggesterSelected.setProjectionRuleModel(prModel);
			resourcesSmartSuggesterSelected.setRDFModel(rdfModel);
			resourcesSmartSuggesterSelected.setCODACore(this);
		}
	}
	
	/**
	 * This method set the Smart Suggestion Triples
	 * 
	 * @param triplesSmartSuggester
	 *            the Smart Suggestion Resources
	 */
	public void setTriplesSmartSuggester(TriplesSmartSuggesterInterface triplesSmartSuggester) {
		triplesSmartSuggesterSelected = triplesSmartSuggester;
		if (triplesSmartSuggesterSelected != null) {
			triplesSmartSuggesterSelected.setProjectionRuleModel(prModel);
			triplesSmartSuggesterSelected.setRDFModel(rdfModel);
			triplesSmartSuggesterSelected.setCODACore(this);
		}
	}

	/**
	 * This method return true if there is another UIMA annotation in the cas, false otherwise
	 * 
	 * @return true if there is another UIMA annotation in the cas, false otherwise
	 */
	public boolean isAnotherAnnotationPrsent() {
		if (iterAnnotation != null)
			return iterAnnotation.hasNext();
		else
			// the iterator was not set
			return false;
	}

	/**
	 * This method set the maximum number of hint that the Projection Disambiguation can return
	 * 
	 * @param maxNumAnswerPD
	 *            the maximum number of hint that the Projection Disambiguation can return
	 */
	public void setMaxNumAnswerPD(int maxNumAnswerPD) {
		this.maxNumAnswerPD = maxNumAnswerPD;
	}

	/**
	 * This method set the maximum number of hint that the Identity Resolution can return
	 * 
	 * @param maxNumAnswerIR
	 *            the maximum number of hint that the Identity Resolution can return
	 */
	public void setMaxNumAnswerIR(int maxNumAnswerIR) {
		this.maxNumAnswerIR = maxNumAnswerIR;
	}

	/**
	 * This method set the maximum number of hint that the Resources Smart Suggestion can return
	 * 
	 * @param maxNumAnswerRSS
	 *            the maximum number of hint that the Resources Smart Suggestion can return
	 */
	public void setMaxNumAnswerRSS(int maxNumAnswerRSS) {
		this.maxNumAnswerRSS = maxNumAnswerRSS;
	}
	
	/**
	 * This method set the maximum number of hint that the Triples Smart Suggestion can return
	 * 
	 * @param maxNumAnswerTSS
	 *            the maximum number of hint that the Triples Smart Suggestion can return
	 */
	public void setMaxNumAnswerTSS(int maxNumAnswerTSS) {
		this.maxNumAnswerTSS = maxNumAnswerTSS;
	}

	/**
	 * This method process the next UIMA annotation and return the hints from the five modules
	 * 
	 * @return the hints from the five module or null if there are no further UIMA annotation
	 * @throws QueryEvaluationException
	 * @throws MalformedQueryException
	 * @throws ModelAccessException
	 * @throws UnsupportedQueryLanguageException
	 */
	public SuggOntologyCoda processNextAnnotation() throws UnsupportedQueryLanguageException,
			ModelAccessException, MalformedQueryException, QueryEvaluationException, CODAComponentNotSetException {
		
		//check if all the CODA modules are properly set
		if(projectionRuleDeciderSelected == null){
			throw new CODAComponentNotSetException(
				"the Projection Rules Decider is not properly set");
		}
		if(identityResolverSelected == null){
			throw new CODAComponentNotSetException(
				"the Identity Resolver is not properly set");
		}
		if(resourcesSmartSuggesterSelected == null){
			throw new CODAComponentNotSetException(
				"the Resources Smart Suggester is not properly set");
		}
		if(triplesSmartSuggesterSelected == null){
			throw new CODAComponentNotSetException(
				"the Triples Smart Suggester is not properly set");
		}
		
		
		if (isAnotherAnnotationPrsent()) {
			SelectedProjectionRules selProjRules = null;
			BindLabelToExistingARTURIResource bindLabels = null;
			ResourcesSmartSuggesterStruct resSmartSuggStruc = null;
			TriplesSmartSuggestionStruct triSmartSuggStruct = null;
			CodaFinalSuggestions codaFinalSuggs = new CodaFinalSuggestions();
			SuggOntologyCoda suggOntCoda;
			Map<PlaceholderStruct, List<? extends ARTNode>> placeholderNotAliasToARTNodeMap = new HashMap<PlaceholderStruct, List<? extends ARTNode>>();
			Map<PlaceholderStruct, String> placeholderAliasToValueMap = new HashMap<PlaceholderStruct, String>();

			Annotation annotation = (Annotation) iterAnnotation.next();
			CasAnnotationStructure casAnn = new CasAnnotationStructure(jcas, annotation);
			
			// Projection Disambiguation Annotation component part
			projectionRuleDeciderSelected.setCasAnnotation(casAnn);
			projectionRuleDeciderSelected.setMaxNumAnswer(maxNumAnswerPD);
			projectionRuleDeciderSelected.setPrevAnnProj(prevDecision);
			selProjRules = projectionRuleDeciderSelected.invokeComponent();
			
			// Identity Resolution Annotation component part
			identityResolverSelected.setCasAnnotation(casAnn);
			identityResolverSelected.setMaxNumAnswer(maxNumAnswerIR);
			identityResolverSelected.setSelectedProjRules(selProjRules);
			identityResolverSelected.setPrevAnnProj(prevDecision);
			bindLabels = identityResolverSelected.invokeComponent();

			// Resources Smart Suggestion component part
			resourcesSmartSuggesterSelected.setCasAnnotation(casAnn);
			resourcesSmartSuggesterSelected.setMaxNumAnswer(maxNumAnswerRSS);
			resourcesSmartSuggesterSelected.setPrevAnnProj(prevDecision);
			resourcesSmartSuggesterSelected.setSelectedProjRules(selProjRules);
			resourcesSmartSuggesterSelected.setBindLabelToARTURIResource(bindLabels);
			resSmartSuggStruc = resourcesSmartSuggesterSelected.invokeComponent();

			// now examine all suggestion from the three component (PD, IR, RSS) and associate to every 
			// placeholder a ARTNode (taking from the suggestion of the second and third component or 
			// create a new ARTNode)
			setPlaceholderValue(selProjRules, bindLabels, resSmartSuggStruc, placeholderNotAliasToARTNodeMap,
					placeholderAliasToValueMap, annotation, codaFinalSuggs);

			// For every Projection rule selected by the projection disambiguation
			for (ProjectionRule projRule : selProjRules.getProjRuleList()) {

				// execute the SPARQL query
				WhereResult whereResult = executeSPARQLQuery(projRule, placeholderNotAliasToARTNodeMap);
				
				// using the result from the query prepare the final suggestion according to ghe graph pattern
				triplesSmartSuggesterSelected.setCasAnnotation(casAnn);
				triplesSmartSuggesterSelected.setMaxNumAnswer(maxNumAnswerTSS);
				triplesSmartSuggesterSelected.setPrevAnnProj(prevDecision);
				triplesSmartSuggesterSelected.setSelectedProjRules(selProjRules);
				triplesSmartSuggesterSelected.setBindLabelToARTURIResource(bindLabels);
				triplesSmartSuggesterSelected.setResourcesSmartSuggesterStruct(resSmartSuggStruc);
				triplesSmartSuggesterSelected.setPlaceholderNotAliasToARTNodeMap(placeholderNotAliasToARTNodeMap);
				triplesSmartSuggesterSelected.setWhereResult(whereResult);
				triSmartSuggStruct = triplesSmartSuggesterSelected.invokeComponent();
				
				prepareFinalSugg(triSmartSuggStruct, whereResult, placeholderNotAliasToARTNodeMap, projRule, codaFinalSuggs);
			}

			// now add all the suggestion together to have just setof triple
			suggOntCoda = new SuggOntologyCoda(selProjRules, bindLabels, resSmartSuggStruc, 
					triSmartSuggStruct, codaFinalSuggs,	annotation);
			return suggOntCoda;
		} else
			return null;
	}

	private void setPlaceholderValue(SelectedProjectionRules selProjRules,
			BindLabelToExistingARTURIResource bindLabels, ResourcesSmartSuggesterStruct resSmartSuggStruc,
			Map<PlaceholderStruct, List<? extends ARTNode>> placeholderNotAliasToARTNodeMap,
			Map<PlaceholderStruct, String> placeholderAliasToValueMap, Annotation annotation,
			CodaFinalSuggestions codaFinalSuggs) {
		UIMACODAUtilities uimaCodaUtilities = new UIMACODAUtilities();
		List<ProjectionRule> projRuleSelList = selProjRules.getProjRuleList();
		for (ProjectionRule projRuleSel : projRuleSelList) {
			Map<String, PlaceholderStruct> placeholderMap = projRuleSel.getPlaceholderMap();
			Iterator<PlaceholderStruct> placeholderIter = placeholderMap.values().iterator();
			while (placeholderIter.hasNext()) {
				PlaceholderStruct placeholder = placeholderIter.next();
				// first check if the placeholder is an alias
				boolean isAlias = placeholder.isAlias();
				if (isAlias == true) {
					// the placeholder is an alias, so just one value is allow
					String value = uimaCodaUtilities.getValueOfFeatureFromFeatPathOneValue(annotation,
							placeholder);
					placeholderAliasToValueMap.put(placeholder, value);
					// codaFinalSuggs.addPlaceholderToARTNode(projRuleSel, placeholder, artResourceList);
					continue;
				}
				// List<ARTURIResource> artResourceList = smartSuggStruc
				// .getArtResourceFromPlaceholder(placeholder);
				Map<String, ARTURIResource> smartSuggArtResFeatVAlueToMap = resSmartSuggStruc
						.getArtResourceFromPlaceholder(placeholder);
				// if (artResourceList != null) {
				// the smart suggestion found a match
				// placeholderNotAliasToARTNodeMap.put(placeholder, artResourceList);
				// codaFinalSuggs.addPlaceholderToARTNode(projRuleSel, placeholder, artResourceList);
				// continue;
				// }
				Map<String, ARTURIResource> idResArtResFeatVAlueToMap = bindLabels
						.getArtResourceMapFromPlaceholder(placeholder);
				// artResourceList = bindLabels.getArtResourceFromPlaceholder(placeholder);
				// if (artResourceList != null) {
				// the identity resolution found a match
				// placeholderNotAliasToARTNodeMap.put(placeholder, artResourceList);
				// codaFinalSuggs.addPlaceholderToARTNode(projRuleSel, placeholder, artResourceList);
				// continue;
				// }
				// no match was found for all, it is necessary to create a new ARTNode (or a list of ARTNode
				// if the
				// placeholder contains a list of value)
				boolean hasIfElse = placeholder.hasIfElse();
				String uimaTypeAndFeat = "", uri = "";
				if (hasIfElse == true) {
					// the placeholder has an if/else structure, so I need to test each condition to know
					// which uima typeFeat should I use
					List<IfElseStruct> ifElseList = placeholder.getIfElseList();
					for (int i = 0; i < ifElseList.size(); ++i) {
						IfElseStruct ifElse = ifElseList.get(i);
						if (ifElse.isElse() == true) {
							// the condition is an else, so there is no boolean condition to check (and by
							// construction it is the last in the list)
							if (ifElse.isUimaTypeAndFeatSet())
								uimaTypeAndFeat = ifElse.getUimaTypeAndFeat();
							else
								uri = ifElse.getOntoResUri();
							break;
						}
						if (projectionRuleParserSelected.checkCondition(ifElse, placeholderAliasToValueMap,
								annotation) == true) {
							// the boolean condition is true, so I can use the uimaTypeAndFeat of this
							// IfElseStruct
							if (ifElse.isUimaTypeAndFeatSet())
								uimaTypeAndFeat = ifElse.getUimaTypeAndFeat();
							else
								uri = ifElse.getOntoResUri();
							break;
						}
					}
					if (uimaTypeAndFeat.compareTo("") == 0 && uri.compareTo("") == 0)
						continue; // no uimaType or URI could be used because each boolean condition in the
					// if/else gave false
				} else { // the placeholder has no if/else
					uimaTypeAndFeat = placeholder.getTypeAndFeat();
				}
				List<String> valueFromUimaTypeAndFeatList = new ArrayList<String>();

				if (uimaTypeAndFeat.compareTo("") != 0) {
					valueFromUimaTypeAndFeatList = uimaCodaUtilities.getValueOfFeatureFromFeatPath(
							annotation, uimaTypeAndFeat);
					if (valueFromUimaTypeAndFeatList == null)
						continue; // no value could be found
				}
				String type = placeholder.getType();
				List<ARTNode> artNodeList = new ArrayList<ARTNode>();

				ARTNode artNode = null;
				if (type.compareToIgnoreCase("uri") == 0) {
					if (valueFromUimaTypeAndFeatList != null && valueFromUimaTypeAndFeatList.size() != 0)
						for (String value : valueFromUimaTypeAndFeatList) {
							if (value.compareTo("") != 0) {
								artNode = null;
								// check if the smartsuggestion has found a match for this value
								if (smartSuggArtResFeatVAlueToMap != null)
									artNode = smartSuggArtResFeatVAlueToMap.get(value);
								if (artNode == null) {
									// the smart suggestion did not found any match, so check the identity
									// resolution
									if (idResArtResFeatVAlueToMap != null)
										artNode = idResArtResFeatVAlueToMap.get(value);
								}
								if (artNode == null) {
									// the smart suggestion and the identity resolution did not found any
									// match, so create a new resource
									artNode = rdfModel.createURIResource(rdfModel.getDefaultNamespace()
											+ value);
								}
								if (artNode != null)
									artNodeList.add(artNode);
							}
						}
					else if (uri.compareTo("") != 0) {
						artNode = rdfModel.createURIResource(uri);
						if (artNode != null)
							artNodeList.add(artNode);
					} else
						continue; // there is a problem with this placeholder
					// placeholderNotAliasToARTNodeMap.put(placeholder, artNode);
					// codaFinalSuggs.addPlaceholderToARTNode(projRuleSel, placeholder, artNode);
				} else if (type.startsWith("plainLiteral")) {
					String[] plainLiteralSplitArray = type.split("\\(");
					if (valueFromUimaTypeAndFeatList != null && valueFromUimaTypeAndFeatList.size() != 0) {
						for (String value : valueFromUimaTypeAndFeatList) {
							if (value.compareTo("") != 0) {
								if (plainLiteralSplitArray.length == 1) { // no language was specified
									artNode = rdfModel.createLiteral(value);
									if (artNode != null)
										artNodeList.add(artNode);
								} else {
									String language = plainLiteralSplitArray[1].split("\\(")[0];
									artNode = rdfModel.createLiteral(value, language);
									if (artNode != null)
										artNodeList.add(artNode);
								}
							} else
								continue; // there is a problem with this placeholder
						}
					}
				} else if (type.startsWith("literal")) {
					int firstOpenPar, lastClosePar;
					firstOpenPar = type.indexOf("(") + 1;
					lastClosePar = type.lastIndexOf(")");
					ARTURIResource typeOfLiteralArtRes = rdfModel.createURIResource(type.substring(
							firstOpenPar, lastClosePar));
					if (valueFromUimaTypeAndFeatList != null && valueFromUimaTypeAndFeatList.size() != 0) {
						for (String value : valueFromUimaTypeAndFeatList) {
							if (value.compareTo("") != 0) {
								artNode = rdfModel.createLiteral(value, typeOfLiteralArtRes);
								if (artNode != null)
									artNodeList.add(artNode);
							} else
								continue; // there is a problem with this placeholder
						}
					}
				}

				if (artNodeList.size() != 0) {
					placeholderNotAliasToARTNodeMap.put(placeholder, artNodeList);
					codaFinalSuggs.addPlaceholderToARTNode(projRuleSel, placeholder, artNodeList);
				}
			}
		}

	}

	private WhereResult executeSPARQLQuery(ProjectionRule projRule,
			Map<PlaceholderStruct, List<? extends ARTNode>> placeholderNotAliasToARTNodeMap)
			throws UnsupportedQueryLanguageException, ModelAccessException, MalformedQueryException,
			QueryEvaluationException {
		WhereResult whereResult = new WhereResult();
		if (projRule.getWhereList().size() == 0)
			return whereResult; // the WHERE part for the projection rule is empty, so there is no reason to
		// execute an empty query

		// Collection<String> varList = projRule.getVarList();

		String queryString = "SELECT *";
		// for (String varName : varList) {
		// queryString += "?" + varName + " ";
		// }
		queryString += "\nWHERE {";
		String notOptionalPart = "";
		String optionalPart = "";

		for (GraphStruct graphSingle : projRule.getWhereList()) {
			String subj = getValueOfGraphSingleWhere(graphSingle.getSubj(), placeholderNotAliasToARTNodeMap,
					projRule);
			String pred = getValueOfGraphSingleWhere(graphSingle.getPred(), placeholderNotAliasToARTNodeMap,
					projRule);
			String obj = getValueOfGraphSingleWhere(graphSingle.getObj(), placeholderNotAliasToARTNodeMap,
					projRule);
			// add to the query the non optional triples
			if (graphSingle.isOptional() == false) {
				notOptionalPart += "\n " + subj + " " + pred + " " + obj + " .";
			}
			// add to the query the optional triples
			else {
				optionalPart += "\n OPTIONAL { " + subj + " " + pred + " " + obj + " }";
			}
		}
		// ADD the WHERE BODY
		queryString += notOptionalPart + optionalPart;
		queryString += "\n}";

		// logger.debug("queryString: \n\t" + queryString);

		Query query = rdfModel.createQuery(QueryLanguage.SPARQL, queryString, rdfModel.getBaseURI());
		TupleBindingsIterator tupleBindIter = ((TupleQuery) query).evaluate(false);
		// if the query produced no result, then this while is skipped
		while (tupleBindIter.hasNext()) {
			TupleBindings tupleBind = tupleBindIter.next();
			Tuple codaTuple = new Tuple();
			Set<String> bindNameSet = tupleBind.getBindingNames();
			for (String varName : bindNameSet) { // the bindNameSet is a subset of the varList
				Binding binding = tupleBind.getBinding(varName);
				ARTNode artNode = binding.getBoundValue();
				codaTuple.addVarValue(varName, artNode);
			}
			whereResult.addTuple(codaTuple);
		}
		return whereResult;
	}

	private String getValueOfGraphSingleWhere(GraphSingleElement graphSingleElement,
			Map<PlaceholderStruct, List<? extends ARTNode>> placeholderMap, ProjectionRule projRule) {
		List<ARTNodeAndString> valueList = getValueOfGraphSingle(graphSingleElement, placeholderMap, true,
				null, projRule);
		// In the where for the moment I consider only the first value
		// TODO find a way to consider all the value
		if (valueList.size() == 0)
			return "";
		ARTNodeAndString artNodeAndString = valueList.get(0);
		if (artNodeAndString.isARTNodeSet()) {
			ARTNode artNode = artNodeAndString.getArtNode();
			if (artNode.isURIResource())
				return "<" + artNode.asURIResource().getURI() + ">";
			else if (artNode.isLiteral())
				return artNode.asLiteral().getLabel();
			else
				return "";
		} else
			return artNodeAndString.getString();
	}

	private List<ARTNodeAndString> getValueOfGraphSingle(GraphSingleElement graphSingleElement,
			Map<PlaceholderStruct, List<? extends ARTNode>> placeholderToValueList, boolean isWhere,
			Tuple tuple, ProjectionRule projRule) {
		List<ARTNodeAndString> valueList = new ArrayList<ARTNodeAndString>();

		if (graphSingleElement instanceof GraphSingleElemUri) {
			GraphSingleElemUri graphElemUri = (GraphSingleElemUri) graphSingleElement;
			if (isWhere)
				valueList.add(new ARTNodeAndString("<" + graphElemUri.getURI() + ">"));
			else
				valueList.add(new ARTNodeAndString(graphElemUri.getURI()));
		} else if (graphSingleElement instanceof GraphSingleElemVar) {
			GraphSingleElemVar graphElemVar = (GraphSingleElemVar) graphSingleElement;
			String varId = graphElemVar.getVarId();
			if (isWhere) {
				valueList.add(new ARTNodeAndString("?" + varId));
			} else { // the value associated to the var should be used
				PlaceholderStruct placeholder = projRule.getPlaceholderMap().get(varId);
				if (tuple.getTupleMap().get(varId) != null) {
					valueList.add(new ARTNodeAndString(tuple.getTupleMap().get(varId)));
				} else if (placeholder != null && placeholderToValueList.get(placeholder) != null) {
					// the var is null, so I try to find a placeholder with the same name
					List<? extends ARTNode> artNodeList = placeholderToValueList.get(placeholder);
					for (ARTNode artNode : artNodeList)
						valueList.add(new ARTNodeAndString(artNode));
				}
			}
		} else if (graphSingleElement instanceof GraphSingleElemPlaceholder) {
			GraphSingleElemPlaceholder graphElemPlaceholder = (GraphSingleElemPlaceholder) graphSingleElement;
			if (graphElemPlaceholder.hasExternalReference() == true) {
				valueList = resolveExternalReference(graphElemPlaceholder, projRule);
			} else {// no external reference
				PlaceholderStruct placeholder = graphElemPlaceholder.getPlaceholder();
				List<? extends ARTNode> artNodeList = placeholderToValueList.get(placeholder);
				if (artNodeList != null)
					for (ARTNode artNode : artNodeList)
						valueList.add(new ARTNodeAndString(artNode));
			}
		}
		return valueList;
	}

	private List<ARTNodeAndString> resolveExternalReference(GraphSingleElemPlaceholder graphElemPlaceholder,
			ProjectionRule projRule) {
		boolean isExtDepADependsOn;
		List<ARTNodeAndString> valueList = new ArrayList<ARTNodeAndString>();
		// the projection rule id this placeholder depends on
		String otherProjRuleId = graphElemPlaceholder.getOtherProjRuleId();
		// the projection rule identified by that particular id
		ProjectionRule otherProjRule = prModel.getProjRuleFromId(otherProjRuleId);
		if (otherProjRule == null && !graphElemPlaceholder.hasDynRef()) {// no projection rule has that id
			graphElemPlaceholder.setIssue(true);
			return valueList;
		}
		// the uimaType of the projection rule this placeholder depends on
		//String uimaTypeOfOtherProjectionRule = otherProjRule.getUIMAType();
		
		// Iterator on all the projection rules the projection rule to which this Graph element belongs to
		// depends on
		Iterator<DependencyObject> dependsOnIter = projRule.getDependencyList().iterator();
		// the type of the depend (previous, last, etc.)
		String dependsOnType = "";
		boolean found = false;
		DependencyObject dependencyObj = null;
		// search for the DependencyObject instance containing the id of the projection rule this graph
		// elements depends on
		while (dependsOnIter.hasNext() && found == false) {
			dependencyObj = dependsOnIter.next();
			dependsOnType = dependencyObj.getDependsOnType();
			if (dependencyObj.getRuleId().compareTo(otherProjRuleId) == 0) {
				found = true;
			}
		}
		if (found == false) // this should never happen, the right DependsOn was not found
			return valueList;
		else
			// true for DependsOn, false for imports
			isExtDepADependsOn = dependencyObj.isExtDepADependsOn();
		if (dependencyObj instanceof DependencyObjOneParam) {
			// DependsOnOneParam dependsOnOneParam = (DependsOnOneParam) dependsOn;
			if (dependsOnType.compareTo(lastDep) == 0) {
				List<PreviousDecisionSingleElement> prevDecList = prevDecision.getPrevDecSingleElemList();
				int prevDecPos = prevDecList.size() - 1;
				boolean stop = false;
				while (stop == false) {
					PreviousDecisionSingleElement prevDecSingleElem = prevDecList.get(prevDecPos--);
					//String uimaTypeNamePrevAnn = prevDecSingleElem.getsuggOntCoda().getAnnotation().getType()
					//		.getName();
					if (prevDecPos == -1)
						stop = true;
					
					List<ProjectionRule> prList = prevDecSingleElem.getsuggOntCoda().getSelProjRules()
						.getProjRuleList();
					for (ProjectionRule prPast : prList) {
						String prPastId = prPast.getId();
						if (prPastId == null)
							continue;
						if (otherProjRuleId.compareTo(prPastId) == 0) {
							stop = true;
							PlaceholderStruct placeholder = graphElemPlaceholder.getPlaceholder();
							if (placeholder == null)
								return valueList; // = null, the placeholder was not set,this should never happen
							// check if the dependency is an imports type or a dependsOn. If it is a DependsOn
							// type we need to check if the other projection rule failed or succeeded
							boolean otherProjRuleSucc = prevDecSingleElem.getsuggOntCoda().getCodaFinalSuggs()
									.getSuccededFromProjRule(otherProjRule);
							if (isExtDepADependsOn && !otherProjRuleSucc)
								return valueList; // other projection ruled failed and a dependsOn is set
							List<? extends ARTNode> artNodeList = prevDecSingleElem.getsuggOntCoda()
									.getCodaFinalSuggs().getARTNodeFromPlaceholder(placeholder);
							if (artNodeList != null)
								for (ARTNode artNodeSingle : artNodeList)
									valueList.add(new ARTNodeAndString(artNodeSingle));
						}
					}
					//if (uimaTypeNamePrevAnn.compareTo(uimaTypeOfOtherProjectionRule) == 0) {
						//old method (and maybe wrong)
					//}
				}
			}
			// else if(dependsOnType.compareTo(nextDep) == 0){ }
			// else if(dependsOnType.compareTo(encloseDep) == 0){ }
		} else if (dependencyObj instanceof DependencyObjTwoParam) {
			DependencyObjTwoParam dependsOnTwoParam = (DependencyObjTwoParam) dependencyObj;
			if (dependsOnType.compareTo(previousDep) == 0) { // the dependsType is previous
				String uimaTypeAnnToStop = dependsOnTwoParam.getSecondValue();
				List<PreviousDecisionSingleElement> prevDecList = prevDecision.getPrevDecSingleElemList();
				int prevDecPos = prevDecList.size() - 1;
				boolean stop = false;
				while (stop == false) {
					PreviousDecisionSingleElement prevDecSingleElem = prevDecList.get(prevDecPos--);
					SuggOntologyCoda suggOntoCoda = prevDecSingleElem.getsuggOntCoda();
					String uimaTypeNamePrevAnn = suggOntoCoda.getAnnotation().getType()
							.getName();
					//check if it is time to stop going back through the previous decisions/suggestions
					if (uimaTypeNamePrevAnn.compareTo(uimaTypeAnnToStop) == 0 || prevDecPos == -1)
						stop = true;
					
					//if (uimaTypeNamePrevAnn.compareTo(uimaTypeOfOtherProjectionRule) == 0) {
					List<ProjectionRule> prList = suggOntoCoda.getSelProjRules()
						.getProjRuleList();
					for (ProjectionRule prPast : prList) {
						if(prPast != otherProjRule)
							continue;
						PlaceholderStruct placeholder = graphElemPlaceholder.getPlaceholder();
						if (placeholder == null)
							return valueList;// = null, the placeholder was not set,this should never happen
						boolean otherProjRuleSucc = suggOntoCoda.getCodaFinalSuggs()
								.getSuccededFromProjRule(otherProjRule);
						if (isExtDepADependsOn && !otherProjRuleSucc)
							return valueList; // other projection ruled failed and a dependsOn is set
						List<? extends ARTNode> artNodeList = prevDecSingleElem.getsuggOntCoda()
								.getCodaFinalSuggs().getARTNodeFromPlaceholder(placeholder);
						if (artNodeList != null)
							for (ARTNode artNodeSingle : artNodeList)
								valueList.add(new ARTNodeAndString(artNodeSingle));
					}
				}
			}
		} else if (dependencyObj instanceof DependencyObjThreeParam) {
			DependencyObjThreeParam dependsOnThreeParam = (DependencyObjThreeParam) dependencyObj;
			//TODO 
		} else if (dependencyObj instanceof DependencyObjVarParam) {
			DependencyObjVarParam dependsOnVarParam = (DependencyObjVarParam) dependencyObj;
			String[] valuesArray = dependsOnVarParam.getValuesArray();
			if (dependsOnType.compareTo(lastOneOfDep) == 0) { // the dependsType is lastOneOf
				List<PreviousDecisionSingleElement> prevDecList = prevDecision.getPrevDecSingleElemList();
				int prevDecPos = prevDecList.size() - 1;
				boolean stop = false;
				while (stop == false) {
					if (prevDecPos == -1)
						break;
					PreviousDecisionSingleElement prevDecSingleElem = prevDecList.get(prevDecPos--);
					List<ProjectionRule> prList = prevDecSingleElem.getsuggOntCoda().getSelProjRules()
							.getProjRuleList();
					
					ProjectionRule prPastChoosen = null;
					for (ProjectionRule prPast : prList) {
						String prPastId = prPast.getId();
						if (prPastId == null)
							continue;
						if (Arrays.asList(valuesArray).contains(prPastId)) {
							stop = true;
							prPastChoosen = prPast;
							break;
						}
					}
					if (stop == true) {
						// check if the dependency is an imports type or a dependsOn. If it is a DependsOn
						// type we need to check if the other projection rule failed or succeeded
						boolean otherProjRuleSucc = prevDecSingleElem.getsuggOntCoda().getCodaFinalSuggs()
								.getSuccededFromProjRule(prPastChoosen);
						if (isExtDepADependsOn && !otherProjRuleSucc)
							return valueList; // other projection ruled failed and a dependsOn is set
						PlaceholderStruct placeholder = prPastChoosen.getPlaceholderMap().get(
								graphElemPlaceholder.getPlaceholderId());
						List<? extends ARTNode> artNodeList = prevDecSingleElem.getsuggOntCoda()
								.getCodaFinalSuggs().getARTNodeFromPlaceholder(placeholder);
						if (artNodeList != null)
							for (ARTNode artNodeSingle : artNodeList)
								valueList.add(new ARTNodeAndString(artNodeSingle));

					}
				}
			}
		}
		return valueList;
	}

	private void prepareFinalSugg(TriplesSmartSuggestionStruct triSmartSuggStruct, 
			WhereResult whereResult, 
			Map<PlaceholderStruct, List<? extends ARTNode>> placeholderNotAliasToARTNodeMap,
			ProjectionRule projRule, CodaFinalSuggestions codaFinalSuggs) {

		List<GraphStruct> graphWithNoVarList = new ArrayList<GraphStruct>();
		List<GraphStruct> graphWithVarList = new ArrayList<GraphStruct>();
		// divide the triple inside the GRAPH part into two set, one in which no element in the triple has a
		// variable and the other with a least one variable
		List<ARTTriple> artTripleList = new ArrayList<ARTTriple>();
		for (GraphStruct graphStruct : projRule.getGraphList()) {
			//check if the Triple Smart Suggestion has one or more suggestion for the given GraphStruct
			List<ARTTriple> artTripleListFromTSS = triSmartSuggStruct.getARTTriplesListFromGraphStruct(graphStruct);
			if(artTripleListFromTSS != null && artTripleListFromTSS.size() != 0){
				for(ARTTriple artTriple : artTripleListFromTSS)
					artTripleList.add(artTriple);
				// the TSS had one or more suggestion for the given GraphStruct, so these suggestion are added to the 
				// final suggestion from CODA
				continue;
			}
			
			GraphSingleElement subjGraph = graphStruct.getSubj();
			GraphSingleElement predGraph = graphStruct.getPred();
			GraphSingleElement objGraph = graphStruct.getObj();
			if (!(subjGraph instanceof GraphSingleElemVar) && !(predGraph instanceof GraphSingleElemVar)
					&& !(objGraph instanceof GraphSingleElemVar)) {
				// this triple does not contain any variable
				graphWithNoVarList.add(graphStruct);
			} else {
				// the triple contains at least one variable
				graphWithVarList.add(graphStruct);
			}
		}

		// add to the suggestion triple all the graphs that do not have any variable (?var) inside them
		boolean finalSucceeded = true;
		for (GraphStruct grapgStruct : graphWithNoVarList) {
			GraphSingleElement subjGraph = grapgStruct.getSubj();
			GraphSingleElement predGraph = grapgStruct.getPred();
			GraphSingleElement objGraph = grapgStruct.getObj();
			if (!(subjGraph instanceof GraphSingleElemVar) && !(predGraph instanceof GraphSingleElemVar)
					&& !(objGraph instanceof GraphSingleElemVar)) {
				boolean localSucceded = prepareARTTripleFromGraph(grapgStruct,
						placeholderNotAliasToARTNodeMap, null, artTripleList, projRule);
				if (localSucceded == false)
					finalSucceeded = false;
			}
		}
		// then add all the triple that have at least one variable in them
		for (GraphStruct grapgStruct : graphWithVarList) {
			// if the SPARQL query had no result, then the getTupleList() is empty
			for (Tuple tuple : whereResult.getTupleList()) {
				GraphSingleElement subjGraph = grapgStruct.getSubj();
				GraphSingleElement predGraph = grapgStruct.getPred();
				GraphSingleElement objGraph = grapgStruct.getObj();
				if ((subjGraph instanceof GraphSingleElemVar) || (predGraph instanceof GraphSingleElemVar)
						|| (objGraph instanceof GraphSingleElemVar)) {
					boolean localSucceded = prepareARTTripleFromGraph(grapgStruct,
							placeholderNotAliasToARTNodeMap, tuple, artTripleList, projRule);
					if (localSucceded == false)
						finalSucceeded = false;
				}
			}
			if (whereResult.getTupleList().size() == 0) { // the SPARQL query had no result, but the element
				// with the var could still be resolved using the
				// palceholder with the same name
				boolean localSucceded = prepareARTTripleFromGraph(grapgStruct,
						placeholderNotAliasToARTNodeMap, new Tuple(), artTripleList, projRule);
				if (localSucceded == false)
					finalSucceeded = false;
			}
		}

		// if it all the not OPTIONAL triple were added correctly (no issue, at least one value for a
		// variable, etc), these triples can be added to the final suggestion, otherwise no triple can be
		// suggested
		if (finalSucceeded == true) {
			codaFinalSuggs.addProjRuleSucceed(projRule, finalSucceeded);
			for (ARTTriple artTriple : artTripleList) {
				codaFinalSuggs.addTriple(artTriple);
			}
		} else
			codaFinalSuggs.addProjRuleSucceed(projRule, finalSucceeded);

	}

	private boolean prepareARTTripleFromGraph(GraphStruct grapgStruct,
			Map<PlaceholderStruct, List<? extends ARTNode>> placeholderNotAliasToARTNodeMap, Tuple tuple,
			List<ARTTriple> artTripleList, ProjectionRule projRule) {
		if (!grapgStruct.isOptional() && grapgStruct.hasIssue())
			// there is an issue and the triple is not optional, so it failed
			return false;
		List<ARTNode> subjList = getValueOfGraphSingleGraph(grapgStruct.getSubj(),
				placeholderNotAliasToARTNodeMap, tuple, projRule);
		List<ARTNode> predList = getValueOfGraphSingleGraph(grapgStruct.getPred(),
				placeholderNotAliasToARTNodeMap, tuple, projRule);
		List<ARTNode> objList = getValueOfGraphSingleGraph(grapgStruct.getObj(),
				placeholderNotAliasToARTNodeMap, tuple, projRule);
		if ((subjList.size() == 0 || predList.size() == 0 || objList.size() == 0)
				&& !grapgStruct.isOptional())
			return false;
		for (ARTNode subj : subjList) {
			for (ARTNode pred : predList) {
				for (ARTNode obj : objList) {
					if (subj == null || pred == null || obj == null) {
						if (grapgStruct.isOptional())
							continue;
						else
							// one of the element of the triple has a null value and the triple is not
							// optional, so it failed
							return false;
					}
					ARTTriple artTriple = new ARTTriple(subj, pred, obj, projRule.getConfidenceValue());
					artTripleList.add(artTriple);
				}
			}
		}
		return true;
	}

	// tuple can be null
	private List<ARTNode> getValueOfGraphSingleGraph(GraphSingleElement graphSingleElement,
			Map<PlaceholderStruct, List<? extends ARTNode>> placeholderNotAliasMap, Tuple tuple,
			ProjectionRule projRule) {

		List<ARTNodeAndString> artNodeAndStringList = getValueOfGraphSingle(graphSingleElement,
				placeholderNotAliasMap, false, tuple, projRule);

		List<ARTNode> artNodeList = new ArrayList<ARTNode>();
		for (ARTNodeAndString artNodeAndString : artNodeAndStringList) {
			if (artNodeAndString.isARTNodeSet()) {
				artNodeList.add(artNodeAndString.getArtNode());
			} else { // inside artNodeAndString there is a String not an ARTNode
				String valueString = artNodeAndString.getString();
				// TODO this works at the moment only for simple literal, make it work for all other cases
				ARTNode artNode;
				try {
					// try to create a URI from the String value, if it does not succeed it trows a
					// IllegalArgumentException
					artNode = rdfModel.createURIResource(valueString);
				} catch (IllegalArgumentException e) {
					artNode = rdfModel.createLiteral(valueString);
				}

				artNodeList.add(artNode);
			}
		}

		return artNodeList;
	}

	/*
	 * public boolean checkCondition(IfElseStruct ifElse, Map<PlaceholderStruct, String>
	 * placeholderAliasToValueMap, Annotation ann) { return
	 * projectionRuleParserSelected.checkCondition(ifElse, placeholderAliasToValueMap, ann); }
	 */
}
